purpose of notebook

(/) describe & visualize single variables (univariate) (/) gather interesting observations for further investigation (/) gather possible new features for extraction

todos: (-) …

information

name: makeovermonday_2021w22 link: https://data.world/makeovermonday/2021w22 title: 2021/W22: The Plastic Waste Makers Index Data Source: Minderoo from 2019

insights
  1. no_of_assets is poisson distributed, where most producer only have up to 9 (median = 6) assets, some have up to 29 (upper fence = 26), and only a few (outliers) are above that with up to 82 assets
  2. production_of_in_scope_polymers is poisson distributed, likes very similar to no_of_assets, median is 0.9, upper fence is 3.4, max is 11.6 -> might correlate with no_of_assets?
  3. flexible_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets, median is 0.2, upper fence is 1.1, max is 4.7
  4. rigid_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets, median is 0.2, upper fence is 1.1, max is 4.5, very similar to flexible_format_contribution_to_sup_waste, but with less outliers
  5. rigid_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets (again), median is 0.45, upper fence is 1.9, max is 5.9 is sum of flexible_form + rigid_form
  6. ration of sup_waste to produced polymers is between min 0.3 and max 1.0 and has median 0.5, most data lies between 0.4 and 0.6, but there is a high spike at 1.0 (with count 15)
  7. comparing rigid_format and flexible_format shows that up to the upper fence 1.1, the distribution is similar, but there are more bigger (>3) outliers in flexible
load packages
overview
head(plastic)
summary(plastic)
      rank        polymer_producer    no_of_assets   production_of_in_scope_polymers flexible_format_contribution_to_sup_waste rigid_format_contribution_to_sup_waste
 Min.   :  1.00   Length:100         Min.   : 0.00   Min.   : 0.200                  Min.   :0.000                             Min.   :0.000                         
 1st Qu.: 25.75   Class :character   1st Qu.: 3.00   1st Qu.: 0.500                  1st Qu.:0.100                             1st Qu.:0.100                         
 Median : 50.50   Mode  :character   Median : 6.00   Median : 0.900                  Median :0.200                             Median :0.200                         
 Mean   : 50.50                      Mean   :11.56   Mean   : 1.805                  Mean   :0.538                             Mean   :0.416                         
 3rd Qu.: 75.25                      3rd Qu.:12.25   3rd Qu.: 1.700                  3rd Qu.:0.500                             3rd Qu.:0.500                         
 Max.   :100.00                      Max.   :82.00   Max.   :11.600                  Max.   :4.700                             Max.   :4.500                         
 total_contribution_to_sup_waste total_waste_div_production
 Min.   :0.200                   Min.   :0.3000            
 1st Qu.:0.300                   1st Qu.:0.4300            
 Median :0.450                   Median :0.5000            
 Mean   :0.950                   Mean   :0.5834            
 3rd Qu.:0.925                   3rd Qu.:0.6900            
 Max.   :5.900                   Max.   :1.0000            
univariate no_of_assets

no_of_assets is poisson distributed, where most producer only have up to 9 (median = 6) assets, some have up to 29 (upper fence = 26), and only a few (outliers) are above that with up to 82 assets

name = 'no_of_assets'
df <- plastic %>% rename(value = no_of_assets) %>% select(value)

# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
  ggplot(aes(x = value)) +
    # geom_density() +
    geom_histogram(binwidth = 1) +
    # geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
    theme_minimal() +
    scale_y_continuous(breaks = NULL) 
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

boxplot <- df %>%
  ggplot(aes(x = 1, y = value)) +
    geom_boxplot() +
    theme_minimal() +
    coord_flip() +
    ggtitle(paste("distribution of", name, sep=" ")) +
    scale_y_continuous(breaks = NULL) 
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_qq.html 
plot_qq <- df %>%
  ggplot(aes(sample = value)) +
    geom_qq(alpha = 0.5) +
    geom_qq_line() +
    coord_flip() +
    theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))

# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE) 

fig
univariate production_of_in_scope_polymers

production_of_in_scope_polymers is poisson distributed, likes very similar to no_of_assets, median is 0.9, upper fence is 3.4, max is 11.6 might correlate with no_of_assets?

name = 'production_of_in_scope_polymers'
df <- plastic %>% rename(value = production_of_in_scope_polymers) %>% select(value)

# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
  ggplot(aes(x = value)) +
    # geom_density() +
    geom_histogram(binwidth = 0.1) +
    # geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
    theme_minimal() +
    scale_y_continuous(breaks = NULL) 
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

boxplot <- df %>%
  ggplot(aes(x = 1, y = value)) +
    geom_boxplot() +
    theme_minimal() +
    coord_flip() +
    ggtitle(paste("distribution of", name, sep=" ")) +
    scale_y_continuous(breaks = NULL) 
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_qq.html 
plot_qq <- df %>%
  ggplot(aes(sample = value)) +
    geom_qq(alpha = 0.5) +
    geom_qq_line() +
    coord_flip() +
    theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))

# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE) 

fig
univariate flexible_format_contribution_to_sup_waste

flexible_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets, median is 0.2, upper fence is 1.1, max is 4.7

# one variable. continuous x
name = 'flexible_format_contribution_to_sup_waste'
df <- plastic %>% rename(value = flexible_format_contribution_to_sup_waste) %>% select(value)

# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
  ggplot(aes(x = value)) +
    # geom_density() +
    geom_histogram(binwidth = 0.1) +
    # geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
    theme_minimal() +
    scale_y_continuous(breaks = NULL) 
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

boxplot <- df %>%
  ggplot(aes(x = 1, y = value)) +
    geom_boxplot() +
    theme_minimal() +
    coord_flip() +
    ggtitle(paste("distribution of", name, sep=" ")) +
    scale_y_continuous(breaks = NULL) 
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_qq.html 
plot_qq <- df %>%
  ggplot(aes(sample = value)) +
    geom_qq(alpha = 0.5) +
    geom_qq_line() +
    coord_flip() +
    theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))

# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE) 

fig
univariate rigid_format_contribution_to_sup_waste

rigid_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets, median is 0.2, upper fence is 1.1, max is 4.5, very similar to flexible_format_contribution_to_sup_waste, but with less outliers

name = 'rigid_format_contribution_to_sup_waste'
df <- plastic %>% rename(value = rigid_format_contribution_to_sup_waste) %>% select(value)

# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
  ggplot(aes(x = value)) +
    # geom_density() +
    geom_histogram(binwidth = 0.1) +
    # geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
    theme_minimal() +
    scale_y_continuous(breaks = NULL) 
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

boxplot <- df %>%
  ggplot(aes(x = 1, y = value)) +
    geom_boxplot() +
    theme_minimal() +
    coord_flip() +
    ggtitle(paste("distribution of", name, sep=" ")) +
    scale_y_continuous(breaks = NULL) 
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_qq.html 
plot_qq <- df %>%
  ggplot(aes(sample = value)) +
    geom_qq(alpha = 0.5) +
    geom_qq_line() +
    coord_flip() +
    theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))

# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE) 

fig
univariate total_contribution_to_sup_waste

rigid_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets (again), median is 0.45, upper fence is 1.9, max is 5.9 is sum of flexible_form + rigid_form

name = 'total_contribution_to_sup_waste'
df <- plastic %>% rename(value = total_contribution_to_sup_waste) %>% select(value)

# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
  ggplot(aes(x = value)) +
    # geom_density() +
    geom_histogram(binwidth = 0.1) +
    # geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
    theme_minimal() +
    scale_y_continuous(breaks = NULL) 
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

boxplot <- df %>%
  ggplot(aes(x = 1, y = value)) +
    geom_boxplot() +
    theme_minimal() +
    coord_flip() +
    ggtitle(paste("distribution of", name, sep=" ")) +
    scale_y_continuous(breaks = NULL) 
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_qq.html 
plot_qq <- df %>%
  ggplot(aes(sample = value)) +
    geom_qq(alpha = 0.5) +
    geom_qq_line() +
    coord_flip() +
    theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))

# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE) 

fig
univariate total_waste_div_production

ration of sup_waste to produced polymers is between min 0.3 and max 1.0 and has median 0.5, most data lies between 0.4 and 0.6, but there is a high spike at 1.0 (with count 15)

name = 'total_waste_div_production'
df <- plastic %>% rename(value = total_waste_div_production) %>% select(value)

# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
  ggplot(aes(x = value)) +
    # geom_density() +
    geom_histogram(binwidth = 0.01) +
    # geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
    theme_minimal() +
    scale_y_continuous(breaks = NULL) 
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

boxplot <- df %>%
  ggplot(aes(x = 1, y = value)) +
    geom_boxplot() +
    theme_minimal() +
    coord_flip() +
    ggtitle(paste("distribution of", name, sep=" ")) +
    scale_y_continuous(breaks = NULL) 
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_qq.html 
plot_qq <- df %>%
  ggplot(aes(sample = value)) +
    geom_qq(alpha = 0.5) +
    geom_qq_line() +
    coord_flip() +
    theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))

# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE) 

fig
compare rigid_format and flexible_format

comparing rigid_format and flexible_format shows that up to the upper fence 1.1, the distribution is similar, but there are more bigger (>3) outliers in flexible

name = c('flexible_format_contribution_to_sup_waste', 'rigid_format_contribution_to_sup_waste')
df <- plastic %>% rename(flexible = flexible_format_contribution_to_sup_waste, rigid = rigid_format_contribution_to_sup_waste) %>% select(flexible, rigid) %>% pivot_longer(cols = c(flexible,rigid))

boxplot <- df %>%
  ggplot(aes(x = name, y = value, colour = name)) +
    geom_boxplot() +
    theme_minimal() +
    coord_flip() +
    ggtitle(paste("compare ", name[1], "and", name[2], sep=" ")) +
    scale_y_continuous(breaks = NULL) 
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
  ggplot(aes(x = value, fill = name)) +
    # geom_density() +
    geom_histogram(binwidth = 0.1, alpha = 0.5, position = "identity") +
    # geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1, dotsize = 0.23, binwidth = 0.1) +
    theme_minimal() +
    scale_y_continuous(breaks = NULL) 
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_qq.html 
plot_qq <- df %>%
  ggplot(aes(sample = value, colour = name)) +
    geom_qq(alpha = 0.5) +
    geom_qq_line(alpha = 0.5) +
    coord_flip() +
    theme_minimal() 
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = paste(name[1], "&", name[2], sep=" ")))

# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE) 

fig
assets_plot_hist <- plastic %>%
  ggplot(aes(x = no_of_assets)) +
    geom_histogram(binwidth = 1) +
    theme_minimal() +
    ggtitle("Distribution of no_of_assets")

ggplotly(assets_plot_hist)
assets_plot_box <- plastic %>%
  ggplot(aes(x = 1, y = no_of_assets)) +
    geom_boxplot() +
    geom_jitter(alpha = 0.5, width = 0.15) +
    theme_minimal() +
    coord_flip() +
    ggtitle("Distribution of no_of_assets")

ggplotly(assets_plot_box)
assets_plot_box <- plastic %>%
  mutate( x = 1 ) %>%
  ggplot(aes(y = no_of_assets, x=1)) +
    geom_boxplot() +
    geom_dotplot(binaxis='y', stackdir='center', binwidth = 1) +
    theme_minimal() +
    coord_flip() +
    ggtitle("Distribution of no_of_assets")

assets_plot_box

assets_plot_density <- plastic %>%
  ggplot(aes(x = no_of_assets)) +
    geom_histogram(aes(y=..density..)) +
    geom_density() +
    theme_minimal() +
    ggtitle("Distribution of no_of_assets")

ggplotly(assets_plot_density)
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
assets_plot_dot <- plastic %>%
  ggplot(aes(x = no_of_assets)) +
    geom_histogram(binwidth = 1) +
    geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1, binwidth = 1) +
    theme_minimal() +
    scale_y_continuous(breaks = NULL) +
    ggtitle("Distribution of no_of_assets")

assets_plot_dot

name = 'no_of_assets'
df <- plastic %>% rename(y = no_of_assets) %>% select(y)

# https://ggplot2.tidyverse.org/reference/geom_qq.html 
plot_qq <- df %>%
  ggplot(aes(sample = y)) +
    geom_qq() +
    geom_qq_line() +
    theme_minimal() +
    ggtitle(paste("qq plot for", name, sep=" "))
plot_qq <- ggplotly(plot_qq)

# Use fitdistr from MASS to estimate distribution params
# https://rdrr.io/cran/MASS/man/fitdistr.html
params <- as.list(MASS::fitdistr(df$y, "t")$estimate)
NaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugt
plot_qq_fit <- df %>%
  ggplot(aes(sample = y)) +
    geom_qq(distribution = qt, dparams = params["df"]) +
    geom_qq_line(distribution = qt, dparams = params["df"]) +
    theme_minimal() +
    ggtitle(paste("qq plot for", name, "without left and with fitdistr right", sep=" "))
plot_qq_fit <- ggplotly(plot_qq_fit)

# https://plotly.com/r/subplots/
subplot(plot_qq, plot_qq_fit)
name = 'production_of_in_scope_polymers'
df <- plastic %>% rename(y = production_of_in_scope_polymers) %>% select(y)

boxplot <- df %>%
  ggplot(aes(x = 1, y = y)) +
    geom_boxplot() +
    theme_minimal() +
    coord_flip() +
    ggtitle(paste("distribution of", name, sep=" ")) +
    scale_y_continuous(breaks = NULL) 
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
  ggplot(aes(x = y)) +
    # geom_density() +
    # geom_histogram(binwidth = 1) +
    geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 0.1) +
    theme_minimal() +
    scale_y_continuous(breaks = NULL) 
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_qq.html 
plot_qq <- df %>%
  ggplot(aes(sample = y)) +
    geom_qq() +
    geom_qq_line() +
    theme_minimal() 

# Use fitdistr from MASS to estimate distribution params
params <- as.list(MASS::fitdistr(df$y, "t")$estimate)
NaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugt
plot_qq_fit <- df %>%
  ggplot(aes(sample = y)) +
    geom_qq(distribution = qt, dparams = params["df"]) +
    geom_qq_line(distribution = qt, dparams = params["df"]) +
    theme_minimal() 

# https://plotly.com/r/subplots/
s1 <- subplot(dotplot, boxplot, nrows = 2, margin = 0.03, heights = c(0.75, 0.25))
s2 <- subplot(plot_qq, plot_qq_fit)
fig <- subplot(s1, s2, nrows = 2, margin = 0.03, heights = c(0.6, 0.4)) 

fig
LS0tDQp0aXRsZTogImRlc2NyaWJlIGFuZCB2aXN1YWxpemUgcGxhc3RpYyB3YXN0ZSBtYWtlcnMgaW5kZXggZGF0YSAtIHVuaXZhcmlhdGUiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQotLS0NCnB1cnBvc2Ugb2Ygbm90ZWJvb2sNCi0tLQ0KDQogICgvKSBkZXNjcmliZSAmIHZpc3VhbGl6ZSBzaW5nbGUgdmFyaWFibGVzICh1bml2YXJpYXRlKQ0KICAoLykgZ2F0aGVyIGludGVyZXN0aW5nIG9ic2VydmF0aW9ucyBmb3IgZnVydGhlciBpbnZlc3RpZ2F0aW9uDQogICgvKSBnYXRoZXIgcG9zc2libGUgbmV3IGZlYXR1cmVzIGZvciBleHRyYWN0aW9uDQogIA0KdG9kb3M6DQogICgtKSAuLi4NCiAgDQotLS0NCmluZm9ybWF0aW9uDQotLS0NCg0KbmFtZTogbWFrZW92ZXJtb25kYXlfMjAyMXcyMg0KbGluazogaHR0cHM6Ly9kYXRhLndvcmxkL21ha2VvdmVybW9uZGF5LzIwMjF3MjINCnRpdGxlOiAyMDIxL1cyMjogVGhlIFBsYXN0aWMgV2FzdGUgTWFrZXJzIEluZGV4DQpEYXRhIFNvdXJjZTogW01pbmRlcm9vXShodHRwczovL3d3dy5taW5kZXJvby5vcmcvcGxhc3RpYy13YXN0ZS1tYWtlcnMtaW5kZXgvZGF0YS9pbmRpY2VzL3Byb2R1Y2Vycy8pIGZyb20gMjAxOQ0KICANCi0tLQ0KaW5zaWdodHMgDQotLS0NCg0KICAoaSkgbm9fb2ZfYXNzZXRzIGlzIHBvaXNzb24gZGlzdHJpYnV0ZWQsIHdoZXJlIG1vc3QgcHJvZHVjZXIgb25seSBoYXZlIHVwIHRvIDkgKG1lZGlhbiA9IDYpIGFzc2V0cywgc29tZSBoYXZlIHVwIHRvIDI5ICh1cHBlciBmZW5jZSA9IDI2KSwgYW5kIG9ubHkgYSBmZXcgKG91dGxpZXJzKSBhcmUgYWJvdmUgdGhhdCAgICAgICAgd2l0aCB1cCB0byA4MiBhc3NldHMNCiAgKGkpIHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMgaXMgcG9pc3NvbiBkaXN0cmlidXRlZCwgbGlrZXMgdmVyeSBzaW1pbGFyIHRvIG5vX29mX2Fzc2V0cywgbWVkaWFuIGlzIDAuOSwgdXBwZXIgZmVuY2UgaXMgMy40LCBtYXggaXMgMTEuNg0KICAgICAgLT4gbWlnaHQgY29ycmVsYXRlIHdpdGggbm9fb2ZfYXNzZXRzPw0KICAoaSkgZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgaXMgcG9pc3NvbiBkaXN0cmlidXRlZCwgbGlrZXMgdmVyeSBzaW1pbGFyIHRvIG5vX29mX2Fzc2V0cywgbWVkaWFuIGlzIDAuMiwgdXBwZXIgZmVuY2UgaXMgMS4xLCBtYXggaXMgNC43DQogIChpKSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBpcyBwb2lzc29uIGRpc3RyaWJ1dGVkLCBsaWtlcyB2ZXJ5IHNpbWlsYXIgdG8gbm9fb2ZfYXNzZXRzLCBtZWRpYW4gaXMgMC4yLCB1cHBlciBmZW5jZSBpcyAxLjEsIG1heCBpcyA0LjUsDQogICAgICB2ZXJ5IHNpbWlsYXIgdG8gZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUsIGJ1dCB3aXRoIGxlc3Mgb3V0bGllcnMNCiAgKGkpIHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIGlzIHBvaXNzb24gZGlzdHJpYnV0ZWQsIGxpa2VzIHZlcnkgc2ltaWxhciB0byBub19vZl9hc3NldHMgKGFnYWluKSwgbWVkaWFuIGlzIDAuNDUsIHVwcGVyIGZlbmNlIGlzIDEuOSwgbWF4IGlzIDUuOQ0KICAgICAgaXMgc3VtIG9mIGZsZXhpYmxlX2Zvcm0gKyByaWdpZF9mb3JtDQogIChpKSByYXRpb24gb2Ygc3VwX3dhc3RlIHRvIHByb2R1Y2VkIHBvbHltZXJzIGlzIGJldHdlZW4gbWluIDAuMyBhbmQgbWF4IDEuMCBhbmQgaGFzIG1lZGlhbiAwLjUsIG1vc3QgZGF0YSBsaWVzIGJldHdlZW4gMC40IGFuZCAwLjYsIGJ1dCB0aGVyZSBpcyBhIGhpZ2ggc3Bpa2UgYXQgMS4wICh3aXRoIGNvdW50IDE1KQ0KICAoaSkgY29tcGFyaW5nIHJpZ2lkX2Zvcm1hdCBhbmQgZmxleGlibGVfZm9ybWF0IHNob3dzIHRoYXQgdXAgdG8gdGhlIHVwcGVyIGZlbmNlIDEuMSwgdGhlIGRpc3RyaWJ1dGlvbiBpcyBzaW1pbGFyLCBidXQgdGhlcmUgYXJlIG1vcmUgYmlnZ2VyICg+Mykgb3V0bGllcnMgaW4gZmxleGlibGUNCiAgIA0KLS0tDQpsb2FkIHBhY2thZ2VzDQotLS0NCmBgYHtyIGxvYWQgcGFja2FnZXMsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkgIyB0aWR5IGRhdGEgZnJhbWUNCmxpYnJhcnkoZ2d0aGVtZXMpICMgZm9yIGV4dHJhIHBsb3QgdGhlbWVzDQpsaWJyYXJ5KHBsb3RseSkgIyBtYWtlIGdncGxvdHMgaW50ZXJhY3RpdmUNCg0KbGlicmFyeShwYXRjaHdvcmspICMgbWFrZSBpdCByaWRpY3Vsb3VzbHkgc2ltcGxlIHRvIGNvbWJpbmUgc2VwYXJhdGUgZ2dwbG90cyBpbnRvIHRoZSBzYW1lIGdyYXBoaWMgcDEgKyBwMiBvciAocDEgfCBwMiB8IHAzKSAvIHA0DQpsaWJyYXJ5KGRsb29rcikgIyBjb2xsZWN0aW9uIG9mIHRvb2xzIHRoYXQgc3VwcG9ydCBkYXRhIGRpYWdub3NpcywgZXhwbG9yYXRpb24sIGFuZCB0cmFuc2Zvcm1hdGlvbi4NCmBgYA0KDQotLS0NCm92ZXJ2aWV3DQotLS0NCmBgYHtyfQ0KaGVhZChwbGFzdGljKQ0KYGBgDQpgYGB7cn0NCnN1bW1hcnkocGxhc3RpYykNCmBgYA0KDQotLS0NCnVuaXZhcmlhdGUgbm9fb2ZfYXNzZXRzDQotLS0NCm5vX29mX2Fzc2V0cyBpcyBwb2lzc29uIGRpc3RyaWJ1dGVkLCB3aGVyZSBtb3N0IHByb2R1Y2VyIG9ubHkgaGF2ZSB1cCB0byA5IChtZWRpYW4gPSA2KSBhc3NldHMsIHNvbWUgaGF2ZSB1cCB0byAyOSAodXBwZXIgZmVuY2UgPSAyNiksIGFuZCBvbmx5IGEgZmV3IChvdXRsaWVycykgYXJlIGFib3ZlIHRoYXQgd2l0aCB1cCB0byA4MiBhc3NldHMNCg0KYGBge3J9DQojIG9uZSB2YXJpYWJsZSwgY29udGludW91cyB4LCBzaG93IGRpc3RyaWJ1dGlvbg0KbmFtZSA9ICdub19vZl9hc3NldHMnDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUodmFsdWUgPSBub19vZl9hc3NldHMpICU+JSBzZWxlY3QodmFsdWUpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fZG90cGxvdC5odG1sDQpkb3RwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB2YWx1ZSkpICsNCiAgICAjIGdlb21fZGVuc2l0eSgpICsNCiAgICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICAjIGdlb21fZG90cGxvdChtZXRob2Q9Imhpc3RvZG90Iiwgc3RhY2tncm91cHMgPSBUUlVFLCBzdGFja3JhdGlvID0gMS4xLCBkb3RzaXplID0gMS4yLCBiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmRvdHBsb3QgPC0gZ2dwbG90bHkoZG90cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCmJveHBsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IDEsIHkgPSB2YWx1ZSkpICsNCiAgICBnZW9tX2JveHBsb3QoKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGdndGl0bGUocGFzdGUoImRpc3RyaWJ1dGlvbiBvZiIsIG5hbWUsIHNlcD0iICIpKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KYm94cGxvdCA8LSBnZ3Bsb3RseShib3hwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xcS5odG1sIA0KcGxvdF9xcSA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyhzYW1wbGUgPSB2YWx1ZSkpICsNCiAgICBnZW9tX3FxKGFscGhhID0gMC41KSArDQogICAgZ2VvbV9xcV9saW5lKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpDQpwbG90X3FxIDwtIGdncGxvdGx5KHBsb3RfcXEpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lKSkNCg0KIyBodHRwczovL3Bsb3RseS5jb20vci9zdWJwbG90cy8NCmZpZyA8LSBzdWJwbG90KGRvdHBsb3QsIGJveHBsb3QsIHBsb3RfcXEsIG5yb3dzID0gMywgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC41LCAwLjIsIDAuMyksIHNoYXJlWCA9IFRSVUUpIA0KDQpmaWcNCmBgYA0KDQotLS0NCnVuaXZhcmlhdGUgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycw0KLS0tDQpwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzIGlzIHBvaXNzb24gZGlzdHJpYnV0ZWQsIGxpa2VzIHZlcnkgc2ltaWxhciB0byBub19vZl9hc3NldHMsIG1lZGlhbiBpcyAwLjksIHVwcGVyIGZlbmNlIGlzIDMuNCwgbWF4IGlzIDExLjYNCm1pZ2h0IGNvcnJlbGF0ZSB3aXRoIG5vX29mX2Fzc2V0cz8NCg0KYGBge3J9DQojIG9uZSB2YXJpYWJsZSwgY29udGludW91cyB4LCBzaG93IGRpc3RyaWJ1dGlvbg0KbmFtZSA9ICdwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzJw0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHZhbHVlID0gcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycykgJT4lIHNlbGVjdCh2YWx1ZSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9kb3RwbG90Lmh0bWwNCmRvdHBsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHZhbHVlKSkgKw0KICAgICMgZ2VvbV9kZW5zaXR5KCkgKw0KICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xKSArDQogICAgIyBnZW9tX2RvdHBsb3QobWV0aG9kPSJoaXN0b2RvdCIsIHN0YWNrZ3JvdXBzID0gVFJVRSwgc3RhY2tyYXRpbyA9IDEuMSwgZG90c2l6ZSA9IDEuMiwgYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpkb3RwbG90IDwtIGdncGxvdGx5KGRvdHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQpib3hwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAxLCB5ID0gdmFsdWUpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJkaXN0cmlidXRpb24gb2YiLCBuYW1lLCBzZXA9IiAiKSkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmJveHBsb3QgPC0gZ2dwbG90bHkoYm94cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXEuaHRtbCANCnBsb3RfcXEgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoc2FtcGxlID0gdmFsdWUpKSArDQogICAgZ2VvbV9xcShhbHBoYSA9IDAuNSkgKw0KICAgIGdlb21fcXFfbGluZSgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KcGxvdF9xcSA8LSBnZ3Bsb3RseShwbG90X3FxKSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZSkpDQoNCiMgaHR0cHM6Ly9wbG90bHkuY29tL3Ivc3VicGxvdHMvDQpmaWcgPC0gc3VicGxvdChkb3RwbG90LCBib3hwbG90LCBwbG90X3FxLCBucm93cyA9IDMsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuNSwgMC4yLCAwLjMpLCBzaGFyZVggPSBUUlVFKSANCg0KZmlnDQpgYGANCg0KLS0tDQp1bml2YXJpYXRlIGZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlDQotLS0gDQpmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBpcyBwb2lzc29uIGRpc3RyaWJ1dGVkLCBsaWtlcyB2ZXJ5IHNpbWlsYXIgdG8gbm9fb2ZfYXNzZXRzLCBtZWRpYW4gaXMgMC4yLCB1cHBlciBmZW5jZSBpcyAxLjEsIG1heCBpcyA0LjcNCg0KYGBge3J9DQojIG9uZSB2YXJpYWJsZSwgY29udGludW91cyB4LCBzaG93IGRpc3RyaWJ1dGlvbg0KbmFtZSA9ICdmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZScNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh2YWx1ZSA9IGZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlKSAlPiUgc2VsZWN0KHZhbHVlKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX2RvdHBsb3QuaHRtbA0KZG90cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gdmFsdWUpKSArDQogICAgIyBnZW9tX2RlbnNpdHkoKSArDQogICAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjEpICsNCiAgICAjIGdlb21fZG90cGxvdChtZXRob2Q9Imhpc3RvZG90Iiwgc3RhY2tncm91cHMgPSBUUlVFLCBzdGFja3JhdGlvID0gMS4xLCBkb3RzaXplID0gMS4yLCBiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmRvdHBsb3QgPC0gZ2dwbG90bHkoZG90cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCmJveHBsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IDEsIHkgPSB2YWx1ZSkpICsNCiAgICBnZW9tX2JveHBsb3QoKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGdndGl0bGUocGFzdGUoImRpc3RyaWJ1dGlvbiBvZiIsIG5hbWUsIHNlcD0iICIpKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KYm94cGxvdCA8LSBnZ3Bsb3RseShib3hwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xcS5odG1sIA0KcGxvdF9xcSA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyhzYW1wbGUgPSB2YWx1ZSkpICsNCiAgICBnZW9tX3FxKGFscGhhID0gMC41KSArDQogICAgZ2VvbV9xcV9saW5lKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpDQpwbG90X3FxIDwtIGdncGxvdGx5KHBsb3RfcXEpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lKSkNCg0KIyBodHRwczovL3Bsb3RseS5jb20vci9zdWJwbG90cy8NCmZpZyA8LSBzdWJwbG90KGRvdHBsb3QsIGJveHBsb3QsIHBsb3RfcXEsIG5yb3dzID0gMywgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC41LCAwLjIsIDAuMyksIHNoYXJlWCA9IFRSVUUpIA0KDQpmaWcNCmBgYA0KDQotLS0NCnVuaXZhcmlhdGUgcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUNCi0tLQ0KcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgaXMgcG9pc3NvbiBkaXN0cmlidXRlZCwgbGlrZXMgdmVyeSBzaW1pbGFyIHRvIG5vX29mX2Fzc2V0cywgbWVkaWFuIGlzIDAuMiwgdXBwZXIgZmVuY2UgaXMgMS4xLCBtYXggaXMgNC41LA0KdmVyeSBzaW1pbGFyIHRvIGZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlLCBidXQgd2l0aCBsZXNzIG91dGxpZXJzDQoNCmBgYHtyfQ0KIyBvbmUgdmFyaWFibGUsIGNvbnRpbnVvdXMgeCwgc2hvdyBkaXN0cmlidXRpb24NCm5hbWUgPSAncmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUodmFsdWUgPSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSkgJT4lIHNlbGVjdCh2YWx1ZSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9kb3RwbG90Lmh0bWwNCmRvdHBsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHZhbHVlKSkgKw0KICAgICMgZ2VvbV9kZW5zaXR5KCkgKw0KICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xKSArDQogICAgIyBnZW9tX2RvdHBsb3QobWV0aG9kPSJoaXN0b2RvdCIsIHN0YWNrZ3JvdXBzID0gVFJVRSwgc3RhY2tyYXRpbyA9IDEuMSwgZG90c2l6ZSA9IDEuMiwgYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpkb3RwbG90IDwtIGdncGxvdGx5KGRvdHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQpib3hwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAxLCB5ID0gdmFsdWUpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJkaXN0cmlidXRpb24gb2YiLCBuYW1lLCBzZXA9IiAiKSkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmJveHBsb3QgPC0gZ2dwbG90bHkoYm94cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXEuaHRtbCANCnBsb3RfcXEgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoc2FtcGxlID0gdmFsdWUpKSArDQogICAgZ2VvbV9xcShhbHBoYSA9IDAuNSkgKw0KICAgIGdlb21fcXFfbGluZSgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KcGxvdF9xcSA8LSBnZ3Bsb3RseShwbG90X3FxKSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZSkpDQoNCiMgaHR0cHM6Ly9wbG90bHkuY29tL3Ivc3VicGxvdHMvDQpmaWcgPC0gc3VicGxvdChkb3RwbG90LCBib3hwbG90LCBwbG90X3FxLCBucm93cyA9IDMsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuNSwgMC4yLCAwLjMpLCBzaGFyZVggPSBUUlVFKSANCg0KZmlnDQpgYGANCg0KLS0tDQp1bml2YXJpYXRlIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUNCi0tLQ0KcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgaXMgcG9pc3NvbiBkaXN0cmlidXRlZCwgbGlrZXMgdmVyeSBzaW1pbGFyIHRvIG5vX29mX2Fzc2V0cyAoYWdhaW4pLCBtZWRpYW4gaXMgMC40NSwgdXBwZXIgZmVuY2UgaXMgMS45LCBtYXggaXMgNS45DQppcyBzdW0gb2YgZmxleGlibGVfZm9ybSArIHJpZ2lkX2Zvcm0NCg0KYGBge3J9DQojIG9uZSB2YXJpYWJsZSwgY29udGludW91cyB4LCBzaG93IGRpc3RyaWJ1dGlvbg0KbmFtZSA9ICd0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJw0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHZhbHVlID0gdG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSkgJT4lIHNlbGVjdCh2YWx1ZSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9kb3RwbG90Lmh0bWwNCmRvdHBsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHZhbHVlKSkgKw0KICAgICMgZ2VvbV9kZW5zaXR5KCkgKw0KICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xKSArDQogICAgIyBnZW9tX2RvdHBsb3QobWV0aG9kPSJoaXN0b2RvdCIsIHN0YWNrZ3JvdXBzID0gVFJVRSwgc3RhY2tyYXRpbyA9IDEuMSwgZG90c2l6ZSA9IDEuMiwgYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpkb3RwbG90IDwtIGdncGxvdGx5KGRvdHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQpib3hwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAxLCB5ID0gdmFsdWUpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJkaXN0cmlidXRpb24gb2YiLCBuYW1lLCBzZXA9IiAiKSkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmJveHBsb3QgPC0gZ2dwbG90bHkoYm94cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXEuaHRtbCANCnBsb3RfcXEgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoc2FtcGxlID0gdmFsdWUpKSArDQogICAgZ2VvbV9xcShhbHBoYSA9IDAuNSkgKw0KICAgIGdlb21fcXFfbGluZSgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KcGxvdF9xcSA8LSBnZ3Bsb3RseShwbG90X3FxKSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZSkpDQoNCiMgaHR0cHM6Ly9wbG90bHkuY29tL3Ivc3VicGxvdHMvDQpmaWcgPC0gc3VicGxvdChkb3RwbG90LCBib3hwbG90LCBwbG90X3FxLCBucm93cyA9IDMsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuNSwgMC4yLCAwLjMpLCBzaGFyZVggPSBUUlVFKSANCg0KZmlnDQpgYGANCg0KLS0tDQp1bml2YXJpYXRlIHRvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uDQotLS0NCnJhdGlvbiBvZiBzdXBfd2FzdGUgdG8gcHJvZHVjZWQgcG9seW1lcnMgaXMgYmV0d2VlbiBtaW4gMC4zIGFuZCBtYXggMS4wIGFuZCBoYXMgbWVkaWFuIDAuNSwgbW9zdCBkYXRhIGxpZXMgYmV0d2VlbiAwLjQgYW5kIDAuNiwgYnV0IHRoZXJlIGlzIGEgaGlnaCBzcGlrZSBhdCAxLjAgKHdpdGggY291bnQgMTUpDQoNCmBgYHtyfQ0KIyBvbmUgdmFyaWFibGUsIGNvbnRpbnVvdXMgeCwgc2hvdyBkaXN0cmlidXRpb24NCm5hbWUgPSAndG90YWxfd2FzdGVfZGl2X3Byb2R1Y3Rpb24nDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUodmFsdWUgPSB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbikgJT4lIHNlbGVjdCh2YWx1ZSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9kb3RwbG90Lmh0bWwNCmRvdHBsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHZhbHVlKSkgKw0KICAgICMgZ2VvbV9kZW5zaXR5KCkgKw0KICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSkgKw0KICAgICMgZ2VvbV9kb3RwbG90KG1ldGhvZD0iaGlzdG9kb3QiLCBzdGFja2dyb3VwcyA9IFRSVUUsIHN0YWNrcmF0aW8gPSAxLjEsIGRvdHNpemUgPSAxLjIsIGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KZG90cGxvdCA8LSBnZ3Bsb3RseShkb3RwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KYm94cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gMSwgeSA9IHZhbHVlKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgiZGlzdHJpYnV0aW9uIG9mIiwgbmFtZSwgc2VwPSIgIikpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpib3hwbG90IDwtIGdncGxvdGx5KGJveHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3FxLmh0bWwgDQpwbG90X3FxIDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHZhbHVlKSkgKw0KICAgIGdlb21fcXEoYWxwaGEgPSAwLjUpICsNCiAgICBnZW9tX3FxX2xpbmUoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkNCnBsb3RfcXEgPC0gZ2dwbG90bHkocGxvdF9xcSkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWUpKQ0KDQojIGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLw0KZmlnIDwtIHN1YnBsb3QoZG90cGxvdCwgYm94cGxvdCwgcGxvdF9xcSwgbnJvd3MgPSAzLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjUsIDAuMiwgMC4zKSwgc2hhcmVYID0gVFJVRSkgDQoNCmZpZw0KYGBgDQoNCi0tLQ0KY29tcGFyZSByaWdpZF9mb3JtYXQgYW5kIGZsZXhpYmxlX2Zvcm1hdCANCi0tLQ0KY29tcGFyaW5nIHJpZ2lkX2Zvcm1hdCBhbmQgZmxleGlibGVfZm9ybWF0IHNob3dzIHRoYXQgdXAgdG8gdGhlIHVwcGVyIGZlbmNlIDEuMSwgdGhlIGRpc3RyaWJ1dGlvbiBpcyBzaW1pbGFyLCBidXQgdGhlcmUgYXJlIG1vcmUgYmlnZ2VyICg+Mykgb3V0bGllcnMgaW4gZmxleGlibGUNCg0KYGBge3J9DQojIHR3byB2YXJpYWJsZXMsIGJvdGggY29udGludW91cyB4LCBjb21wYXJlIGRpc3RyaWJ1dGlvbnMNCm5hbWUgPSBjKCdmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZScsICdyaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZScpDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUoZmxleGlibGUgPSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSwgcmlnaWQgPSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSkgJT4lIHNlbGVjdChmbGV4aWJsZSwgcmlnaWQpICU+JSBwaXZvdF9sb25nZXIoY29scyA9IGMoZmxleGlibGUscmlnaWQpKQ0KDQpib3hwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBuYW1lLCB5ID0gdmFsdWUsIGNvbG91ciA9IG5hbWUpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJjb21wYXJlICIsIG5hbWVbMV0sICJhbmQiLCBuYW1lWzJdLCBzZXA9IiAiKSkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmJveHBsb3QgPC0gZ2dwbG90bHkoYm94cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fZG90cGxvdC5odG1sDQpkb3RwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB2YWx1ZSwgZmlsbCA9IG5hbWUpKSArDQogICAgIyBnZW9tX2RlbnNpdHkoKSArDQogICAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjEsIGFscGhhID0gMC41LCBwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsNCiAgICAjIGdlb21fZG90cGxvdChtZXRob2Q9Imhpc3RvZG90Iiwgc3RhY2tncm91cHMgPSBUUlVFLCBzdGFja3JhdGlvID0gMSwgZG90c2l6ZSA9IDAuMjMsIGJpbndpZHRoID0gMC4xKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpkb3RwbG90IDwtIGdncGxvdGx5KGRvdHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3FxLmh0bWwgDQpwbG90X3FxIDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHZhbHVlLCBjb2xvdXIgPSBuYW1lKSkgKw0KICAgIGdlb21fcXEoYWxwaGEgPSAwLjUpICsNCiAgICBnZW9tX3FxX2xpbmUoYWxwaGEgPSAwLjUpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnBsb3RfcXEgPC0gZ2dwbG90bHkocGxvdF9xcSkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlKG5hbWVbMV0sICImIiwgbmFtZVsyXSwgc2VwPSIgIikpKQ0KDQojIGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLw0KZmlnIDwtIHN1YnBsb3QoZG90cGxvdCwgYm94cGxvdCwgcGxvdF9xcSwgbnJvd3MgPSAzLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjUsIDAuMiwgMC4zKSwgc2hhcmVYID0gVFJVRSkgDQoNCmZpZw0KYGBgDQoNCg0KDQotLS0NCmFwcGVuZGl4OiBvbGQgZXhwZXJpbWVudGFsIHBsb3RzDQotLS0NCmBgYHtyfQ0KYXNzZXRzX3Bsb3RfaGlzdCA8LSBwbGFzdGljICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBub19vZl9hc3NldHMpKSArDQogICAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKCJEaXN0cmlidXRpb24gb2Ygbm9fb2ZfYXNzZXRzIikNCg0KZ2dwbG90bHkoYXNzZXRzX3Bsb3RfaGlzdCkNCmBgYA0KYGBge3J9DQphc3NldHNfcGxvdF9ib3ggPC0gcGxhc3RpYyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gMSwgeSA9IG5vX29mX2Fzc2V0cykpICsNCiAgICBnZW9tX2JveHBsb3QoKSArDQogICAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUsIHdpZHRoID0gMC4xNSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZ3RpdGxlKCJEaXN0cmlidXRpb24gb2Ygbm9fb2ZfYXNzZXRzIikNCg0KZ2dwbG90bHkoYXNzZXRzX3Bsb3RfYm94KQ0KYGBgDQpgYGB7cn0NCmFzc2V0c19wbG90X2JveCA8LSBwbGFzdGljICU+JQ0KICBtdXRhdGUoIHggPSAxICkgJT4lDQogIGdncGxvdChhZXMoeSA9IG5vX29mX2Fzc2V0cywgeD0xKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICsNCiAgICBnZW9tX2RvdHBsb3QoYmluYXhpcz0neScsIHN0YWNrZGlyPSdjZW50ZXInLCBiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9uIG9mIG5vX29mX2Fzc2V0cyIpDQoNCmFzc2V0c19wbG90X2JveA0KYGBgDQpgYGB7cn0NCmFzc2V0c19wbG90X2RlbnNpdHkgPC0gcGxhc3RpYyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gbm9fb2ZfYXNzZXRzKSkgKw0KICAgIGdlb21faGlzdG9ncmFtKGFlcyh5PS4uZGVuc2l0eS4uKSkgKw0KICAgIGdlb21fZGVuc2l0eSgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUoIkRpc3RyaWJ1dGlvbiBvZiBub19vZl9hc3NldHMiKQ0KDQpnZ3Bsb3RseShhc3NldHNfcGxvdF9kZW5zaXR5KQ0KYGBgDQpgYGB7cn0NCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fZG90cGxvdC5odG1sDQphc3NldHNfcGxvdF9kb3QgPC0gcGxhc3RpYyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gbm9fb2ZfYXNzZXRzKSkgKw0KICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGdlb21fZG90cGxvdChtZXRob2Q9Imhpc3RvZG90Iiwgc3RhY2tncm91cHMgPSBUUlVFLCBzdGFja3JhdGlvID0gMS4xLCBkb3RzaXplID0gMSwgYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgKw0KICAgIGdndGl0bGUoIkRpc3RyaWJ1dGlvbiBvZiBub19vZl9hc3NldHMiKQ0KDQphc3NldHNfcGxvdF9kb3QNCmBgYA0KYGBge3J9DQpuYW1lID0gJ25vX29mX2Fzc2V0cycNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh5ID0gbm9fb2ZfYXNzZXRzKSAlPiUgc2VsZWN0KHkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXEuaHRtbCANCnBsb3RfcXEgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoc2FtcGxlID0geSkpICsNCiAgICBnZW9tX3FxKCkgKw0KICAgIGdlb21fcXFfbGluZSgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInFxIHBsb3QgZm9yIiwgbmFtZSwgc2VwPSIgIikpDQpwbG90X3FxIDwtIGdncGxvdGx5KHBsb3RfcXEpDQoNCiMgVXNlIGZpdGRpc3RyIGZyb20gTUFTUyB0byBlc3RpbWF0ZSBkaXN0cmlidXRpb24gcGFyYW1zDQojIGh0dHBzOi8vcmRyci5pby9jcmFuL01BU1MvbWFuL2ZpdGRpc3RyLmh0bWwNCnBhcmFtcyA8LSBhcy5saXN0KE1BU1M6OmZpdGRpc3RyKGRmJHksICJ0IikkZXN0aW1hdGUpDQpwbG90X3FxX2ZpdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyhzYW1wbGUgPSB5KSkgKw0KICAgIGdlb21fcXEoZGlzdHJpYnV0aW9uID0gcXQsIGRwYXJhbXMgPSBwYXJhbXNbImRmIl0pICsNCiAgICBnZW9tX3FxX2xpbmUoZGlzdHJpYnV0aW9uID0gcXQsIGRwYXJhbXMgPSBwYXJhbXNbImRmIl0pICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInFxIHBsb3QgZm9yIiwgbmFtZSwgIndpdGhvdXQgbGVmdCBhbmQgd2l0aCBmaXRkaXN0ciByaWdodCIsIHNlcD0iICIpKQ0KcGxvdF9xcV9maXQgPC0gZ2dwbG90bHkocGxvdF9xcV9maXQpDQoNCiMgaHR0cHM6Ly9wbG90bHkuY29tL3Ivc3VicGxvdHMvDQpzdWJwbG90KHBsb3RfcXEsIHBsb3RfcXFfZml0KQ0KYGBgDQpgYGB7cn0NCm5hbWUgPSAncHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycycNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh5ID0gcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycykgJT4lIHNlbGVjdCh5KQ0KDQpib3hwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAxLCB5ID0geSkpICsNCiAgICBnZW9tX2JveHBsb3QoKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGdndGl0bGUocGFzdGUoImRpc3RyaWJ1dGlvbiBvZiIsIG5hbWUsIHNlcD0iICIpKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KYm94cGxvdCA8LSBnZ3Bsb3RseShib3hwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9kb3RwbG90Lmh0bWwNCmRvdHBsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHkpKSArDQogICAgIyBnZW9tX2RlbnNpdHkoKSArDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICBnZW9tX2RvdHBsb3QobWV0aG9kPSJoaXN0b2RvdCIsIHN0YWNrZ3JvdXBzID0gVFJVRSwgc3RhY2tyYXRpbyA9IDEuMSwgZG90c2l6ZSA9IDEuMiwgYmlud2lkdGggPSAwLjEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmRvdHBsb3QgPC0gZ2dwbG90bHkoZG90cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXEuaHRtbCANCnBsb3RfcXEgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoc2FtcGxlID0geSkpICsNCiAgICBnZW9tX3FxKCkgKw0KICAgIGdlb21fcXFfbGluZSgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQoNCiMgVXNlIGZpdGRpc3RyIGZyb20gTUFTUyB0byBlc3RpbWF0ZSBkaXN0cmlidXRpb24gcGFyYW1zDQpwYXJhbXMgPC0gYXMubGlzdChNQVNTOjpmaXRkaXN0cihkZiR5LCAidCIpJGVzdGltYXRlKQ0KcGxvdF9xcV9maXQgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoc2FtcGxlID0geSkpICsNCiAgICBnZW9tX3FxKGRpc3RyaWJ1dGlvbiA9IHF0LCBkcGFyYW1zID0gcGFyYW1zWyJkZiJdKSArDQogICAgZ2VvbV9xcV9saW5lKGRpc3RyaWJ1dGlvbiA9IHF0LCBkcGFyYW1zID0gcGFyYW1zWyJkZiJdKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KDQojIGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLw0KczEgPC0gc3VicGxvdChkb3RwbG90LCBib3hwbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAuMDMsIGhlaWdodHMgPSBjKDAuNzUsIDAuMjUpKQ0KczIgPC0gc3VicGxvdChwbG90X3FxLCBwbG90X3FxX2ZpdCkNCmZpZyA8LSBzdWJwbG90KHMxLCBzMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLjAzLCBoZWlnaHRzID0gYygwLjYsIDAuNCkpIA0KDQpmaWcNCmBgYA0KDQoNCg0K